#!/bin/bash
#	markit  4.2.9.1149  2021-06-04T11:10:33.646600-05:00 (CDT)  https://github.com/BradleyA/markit.git  master  uthree  three.cptx86.com 4.2.8-1-g675dc09  
#	   markit -->   correct Test case SA-shellcheck-001 markit  
#	markit  4.2.7.1146  2021-06-04T10:51:14.392781-05:00 (CDT)  https://github.com/BradleyA/markit.git  master  uthree  three.cptx86.com 4.2.6-5-g803e81d  
#	   markit -->   updated display_help and examples  
#	markit  4.2.1.1114  2020-12-22T21:02:03.686774-06:00 (CST)  https://github.com/BradleyA/markit.git  master  uadmin  three-rpi3b.cptx86.com 4.1.146-24-g68844ef  
#	   check-markit find-code.sh markit -->   release ready for production  
#86# markit
#	I created this script because Git fails me when it comes to including a
#	version number and a change description in each file being checked-in.
#
#       I want to know what version a piece of code is on any system running
#       it. The system may or may not be connected to any network. The system
#       may or may not have Git installed. The system may or may not have a
#       GitHub repository or Bitbucket repository or GitLab project installed
#       on it. I want the same solution for several types of code (.sh, .go,
#       .yml, .xml, .mk, dockerfile, .txt, etc). I want any person without
#       knowledge of Git or GitHub or Bitbucket or GitLab to be able to answer
#       one question over the phone;
#                       What version are you running?
#
#	Released files need a version number in text when checked in!
#       This is not for your kernal, just files.  Bite me!  and  Merge that!
###
###  Production standard 5.3.559 Copyright                                    # 3.559
#    Copyright (c) 2020 Bradley Allen                                                # 3.555
#    MIT License is online in the repository as a file named LICENSE"         # 3.559
###  Production standard 3.0 shellcheck
###  Production standard 1.3.614 DEBUG variable
#    Order of precedence: environment variable, default code
if [[ "${DEBUG}" == ""  ]] ; then DEBUG="0" ; fi   # 0 = debug off, 1 = debug on, 'export DEBUG=1', 'unset DEBUG' to unset environment variable (bash)
if [[ "${DEBUG}" == "2" ]] ; then set -x    ; fi   # Print trace of simple commands before they are executed
if [[ "${DEBUG}" == "3" ]] ; then set -v    ; fi   # Print shell input lines as they are read
if [[ "${DEBUG}" == "4" ]] ; then set -e    ; fi   # Exit immediately if non-zero exit status
if [[ "${DEBUG}" == "5" ]] ; then set -e -o pipefail ; fi   # Exit immediately if non-zero exit status and exit if any command in a pipeline errors
#
BOLD=$(tput -Txterm bold)
UNDERLINE=$(tput -Txterm sgr 0 1)  # 0.3.583
NORMAL=$(tput -Txterm sgr0)
RED=$(tput    setaf 1)
YELLOW=$(tput setaf 3)
BLUE=$(tput   setaf 4)
PURPLE=$(tput setaf 5)
CYAN=$(tput   setaf 6)
WHITE=$(tput  setaf 7)

###  Production standard 7.0 Default variable value
BRANCH=""

###  Production standard 8.3.541 --usage
COMMAND_NAME=$(echo "${0}" | sed 's/^.*\///')                                               # 3.541
display_usage() {
echo -e "\n${NORMAL}${COMMAND_NAME}\n   add Git verion control information, push to GitHub or Bitbucket or GitLab"
echo -e "\n${BOLD}USAGE${NORMAL}"
echo -e "   ${COMMAND_NAME} [no | normal | all]\n"
echo    "   ${COMMAND_NAME} [--help | -help | help | -h | h | -?]"
echo    "   ${COMMAND_NAME} [--usage | -usage | -u]"
echo    "   ${COMMAND_NAME} [--version | -version | -v]"
}

###  Production standard 0.3.615 --help
display_help() {
display_usage
#    Displaying help DESCRIPTION in English en_US.UTF-8, en.UTF-8, C.UTF-8                  # 3.550
echo -e "\n${BOLD}DESCRIPTION${NORMAL}"
echo    "Markit is a simple bash script that adds Git verion control information to"
echo    "files while being pushed to GitHub, Bitbucket, or GitLab (Supported files:"
echo    "Shell(sh|bash|csh|tcsh|ksh), Go, Dockerfile, YAML, Makefile, Scala,"
echo    "Terraform, Python, Java, PHP, C, C++, JavaScript, Perl, Ruby, PowerShell,"
echo    "Ri, C header, C++ header, HTML, Kotlin, Pascal, R, Rust, Text, XML . . ."
echo -e "\nMarkit supports Semantic Versioning (MAJOR.MINOR.PATCH) and alphanumeric"
echo    "versioning (1.2.5-beta.1).  Markit will display the current version before"
echo    "prompting you to enter the next version.  Markit includes the number of"
echo    "commits with the version in the file(s).  I find this helpful when"
echo    "commiting several different changes while working on the same PATCH."
echo -e "\nMarkit adds two comment lines with information about file changes to all"
echo    "modified tracked file(s) in your local Git repository.  Then pushes those"
echo    "modified file(s) to either a GitHub repository or Bitbucket repository or"
echo    "GitLab project.  If environment variable MARKITLOCAL is set to 1, markit"
echo    "adds two comment lines, commits modified tracked file(s) in your local"
echo    "Git repository, but does not push to remote Git repository.  I find this"
echo    "helpful when working without network access to a remote Git repository."
echo -e "\nThe first comment line includes file name, version.commit, date, time,"
echo    "time zone, repository URL, Git branch, user, hostname, and previous"
echo    "version. The second comment line includes updated file name(s) and a"
echo    "brief description about changes made to the file(s)."
echo -e "\nThere will be a prompt to add comment character(s) for unknown file names"
echo    "when needed and a prompt to add a description about the changes."
echo -e "\nMarkit only modifies Git tracked file(s) by default.  To change a Git"
echo    "untracked file to a Git tracked file enter, 'git add <file_name>'.  To"
echo    "include all tracked and untracked file(s) enter, 'markit all'.  To"
echo    "prevent an untracked file from being tracked, add file(s) to .gitignore"
echo    "file."
echo -e "\nThere are several different methods to 'git push' to more than one repository"
echo    "while using markit.  One method is to edit <repository>/.git/config and add a"
echo    "pushurl line for each additional repository in the [remote \"origin\"] section."
echo    "   [remote \"origin\"]"
echo    "      url     = https://github.com/BradleyA/markit.git"
echo    "      pushurl = https://github.com/BradleyA/markit.git"
echo    "      pushurl = https://axebbq@bitbucket.org/axebbq/markit.git"
echo    "      pushurl = https://BradleyAxe@gitlab.com/BradleyAxe/markit.git"
echo    "      fetch   = +refs/heads/*:refs/remotes/origin/*"

###  Production standard 4.3.587 Documentation Language                                     # 3.550
#    Displaying help DESCRIPTION in French fr_CA.UTF-8, fr_FR.UTF-8, fr_CH.UTF-8
if [[ "${LANG}" == "fr_CA.UTF-8" ]] || [[ "${LANG}" == "fr_FR.UTF-8" ]] || [[ "${LANG}" == "fr_CH.UTF-8" ]] ; then
  echo -e "\n--> ${LANG}"
  echo    "<Votre aide va ici>" # Your help goes here
  echo    "Souhaitez-vous traduire la section description?" # Would you like to translate the description section?
elif ! [[ "${LANG}" == "en_US.UTF-8" ||  "${LANG}" == "en.UTF-8" || "${LANG}" == "C.UTF-8" ]] ; then  # 3.550
  new_message "${LINENO}" "${YELLOW}INFO${WHITE}" "  Your language, ${LANG}, is not supported.  Would you like to translate the description section?" 1>&2
fi

echo -e "\n${BOLD}ENVIRONMENT VARIABLES${NORMAL}"
echo    "If using the bash shell, enter; 'export DEBUG=1' on the command line to set"
echo    "the environment variable DEBUG to '1' (0 = debug off, 1 = debug on).  Use the"
echo    "command, 'unset DEBUG' to remove the exported information from the environment"
echo    "variable DEBUG.  You are on your own defining environment variables if"
echo    "you are using other shells."

###  Production standard 1.3.614 DEBUG variable
echo    "   DEBUG           (default off '0')  The DEBUG environment variable can be set"   # 3.550
echo    "                   to 0, 1, 2, 3, 4 or 5.  The setting '' or 0 will turn off"      # 3.550
echo    "                   all DEBUG messages during execution of this script.  The"       # 3.550
echo    "                   setting 1 will print all DEBUG messages during execution."      # 3.550
echo    "                   Setting 2 (set -x) will print a trace of simple commands"       # 3.550
echo    "                   before they are executed.  Setting 3 (set -v) will print"       # 3.550
echo    "                   shell input lines as they are read.  Setting 4 (set -e) will"   # 3.550
echo    "                   exit immediately if non-zero exit status is recieved with"      # 3.550
echo    "                   some exceptions.  Setting 5 (set -e -o pipefail) will do"       # 3.550
echo    "                   setting 4 and exit if any command in a pipeline errors.  For"   # 3.550
echo    "                   more information about the set options, see man bash."          # 3.550

echo    "   MARKITLOCAL     push to remote Git repository (default '0')"
echo    "                   export MARKITLOCAL=1 only commit to local Git repository, do not"
echo    "                   push to remote Git repository"

echo -e "\n${BOLD}OPTIONS${NORMAL}"
echo -e "Order of precedence: CLI options, environment variable, default value.\n"                     # 0.3.595
echo    "   --help, -help, help, -h, h, -?"                                                            # 0.3.595
echo -e "\tOn-line brief reference manual\n"                                                           # 0.3.595
echo    "   --usage, -usage, -u"                                                                       # 0.3.595
echo -e "\tOn-line command usage\n"                                                                    # 0.3.595
echo    "   --version, -version, -v"                                                                   # 0.3.595
echo -e "\tOn-line command version\n"                                                                  # 0.3.595

echo -e "   UNTRACKED_FILES - used to specify the handling of untracked files"
echo    "      no           no untracked files (default)"
echo    "      normal       untracked files and directories"
echo    "      all          Also individual files in untracked directories"

echo -e "\n${BOLD}DOCUMENTATION${NORMAL}"
echo    "   ${UNDERLINE}https://github.com/BradleyA/markit/blob/master/README.md#markit${NORMAL}"  # 0.3.583"

echo -e "\n${BOLD}EXAMPLES${NORMAL}"
echo -e "   Mark tracked file(s) and push to remote Git repository\n\t${BOLD}${COMMAND_NAME}${NORMAL}\n" #  3.550
echo -e "   Mark tracked and untracked files, directories, and files in untracked\n  directories\n\t${BOLD}${COMMAND_NAME} all${NORMAL}\n"  # 3.550
echo -e "   Mark tracked file(s) but don't push to remote Git repository, only update\n   local repository\n\t${BOLD}export MARKITLOCAL=1 ; ${COMMAND_NAME} ; unset MARKITLOCAL${NORMAL}\n"  # 3.550

echo -e "\n${BOLD}SEE ALSO${NORMAL}"                                                                          #  0.3.615
echo    "   ${BOLD}check-markit${NORMAL}  Check the release version of a file"                                #  0.3.615
echo -e "\twith the remote Git repository release version"                                                    #  0.3.615
echo -e "\t(${UNDERLINE}https://github.com/BradleyA/markit/blob/master/README.md${NORMAL})\n"                 #  0.3.615
echo    "   ${BOLD}find-code.sh${NORMAL}  Search each system found in"                                        #  0.3.615
echo -e "\t<DATA_DIR>/<SYSTEMS_FILE> file for .git repositories in ~/.. directories"                          #  0.3.615
echo -e "\t(${UNDERLINE}https://github.com/BradleyA/markit/blob/master/README.md#usage-find-codesh${NORMAL})" #  0.3.615

echo -e "\n${BOLD}AUTHOR${NORMAL}"                                                          # 3.550
echo    "   ${COMMAND_NAME} was written by Bradley Allen <allen.bradley@ymail.com>"         # 3.550

echo -e "\n${BOLD}REPORTING BUGS${NORMAL}"                                                  # 3.550
echo    "   Report ${COMMAND_NAME} bugs ${UNDERLINE}https://github.com/BradleyA/markit/issues/new/choose${NORMAL}"  # 0.3.579

###  Production standard 5.3.559 Copyright                                            # 3.559
echo -e "\n${BOLD}COPYRIGHT${NORMAL}"                                                       # 3.550
echo    "   Copyright (c) 2020 Bradley Allen"                                               # 3.550
echo    "   MIT License is online in the repository as a file named LICENSE"          # 3.559
}

#    Date and time function ISO 8601
get_date_stamp() {
  DATE_STAMP=$(date +%Y-%m-%dT%H:%M:%S.%6N%:z)
  TEMP=$(date +%Z)
  DATE_STAMP="${DATE_STAMP} (${TEMP})"
}

#    Fully qualified domain name FQDN hostname
LOCALHOST=$(hostname -f)

#    Version
#    Assumptions for the next two lines of code:  The second line in this script includes the script path & name as the second item and
#    the script version as the third item separated with space(s).  The tool I use is called 'markit'. See example line below:
#       template/template.sh  3.517.783  2019-09-13T18:20:42.144356-05:00 (CDT)  https://github.com/BradleyA/user-files.git  uadmin  one-rpi3b.cptx86.com 3.516  
SCRIPT_NAME=$(head -2 "${0}" | awk '{printf $2}')  #  Different from ${COMMAND_NAME}=$(echo "${0}" | sed 's/^.*\///'), SCRIPT_NAME = includes Git repository directory and can be used any where in script (for dev, test teams)
SCRIPT_VERSION=$(head -2 "${0}" | awk '{printf $3}')
if [[ "${SCRIPT_NAME}" == "" ]] ; then SCRIPT_NAME="${0}" ; fi
if [[ "${SCRIPT_VERSION}" == "" ]] ; then SCRIPT_VERSION="v?.?" ; fi

#    GID
GROUP_ID=$(id -g)

###  Production standard 2.3.614 Log format (WHEN WHERE WHAT Version Line WHO UID:GID [TYPE] Message)
new_message() {  #  $1="${LINENO}"  $2="DEBUG INFO ERROR WARN"  $3="message"
  get_date_stamp
  echo -e "${NORMAL}${DATE_STAMP} ${LOCALHOST} ${BOLD}${CYAN}${SCRIPT_NAME}${NORMAL}[$$] ${BOLD}${BLUE}${SCRIPT_VERSION} ${PURPLE}${1}${NORMAL} ${USER} ${UID}:${GROUP_ID} ${BOLD}[${2}]${NORMAL}  ${3}"  # 2.3.614
}

#    INFO
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}INFO${WHITE}" "${BOLD}${CYAN}  Started...${NORMAL}" 1>&2 ; fi  # 1.3.614

#    DEBUG  #  1.3.614
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  Name_of_command >${YELLOW}${SCRIPT_NAME}${WHITE}< Name_of_arg1 >${YELLOW}${1}${WHITE}< Name_of_arg2 >${YELLOW}${2}${WHITE}< Name_of_arg3 >${YELLOW}${3}${WHITE}<  Version of bash ${YELLOW}${BASH_VERSION}${WHITE}" 1>&2 ; fi  #  1.3.614

###  Production standard 9.3.606 Parse CLI options and arguments
while [[ "${#}" -gt 0 ]] ; do
  case "${1}" in
    --help|-help|help|-h|h|-\?)  display_help | more ; exit 0 ;;
    --usage|-usage|usage|-u)  display_usage ; exit 0  ;;
    --version|-version|version|-v)  echo "${SCRIPT_NAME} ${SCRIPT_VERSION}" ; exit 0  ;;
    *) echo -e "\n${BOLD}    Invalid option, ${YELLOW}${1}${WHITE}, try ${YELLOW}--usage${NORMAL}\n" ; exit 1 ; ;; # 9.3.606
  esac
done

###

#    Check if bash-completion/completions/git file on system
if [[ -e /usr/share/bash-completion/completions/git ]] ; then
  #  This is to support __gitdir in the following section
  source /usr/share/bash-completion/completions/git
else
  new_message "${LINENO}" "${YELLOW}INFO${WHITE}" "  /usr/share/bash-completion/completions/git NOT found" 1>&2
fi

#    Check if in Git repository
if ! $( __gitdir > /dev/null 2>&1 ) ; then
  new_message "${LINENO}" "${RED}ERROR${WHITE}" "  Check if you are in a Git repository and you have Git permission.  Current directory $(pwd)" 1>&2
  exit 1
fi

#    Check if environment variable, default 0
if [[ "${MARKITLOCAL}" == "" ]] ; then MARKITLOCAL="0" ; fi

#    Check if remote Git repository has been setup #28
git rev-list HEAD 1> /dev/null || { new_message "${LINENO}" "${RED}ERROR${WHITE}" "  Remote Git repository has not been setup or git clone <remote-repository> was not used to pull remote Git repository before using markit.  ${BOLD}${YELLOW}A remote Git repository is required before markit will work with local or remote repositories.${NORMAL}" 1>&2 ; exit 1; }

#
UNTRACKED_FILES=${1:-no}
BEGIN_COMMENT_CHAR=""
END_COMMENT_CHAR=""
REMOTE_REPOSITORY=$(git ls-remote --get-url)
TEMP_FILE="TEMP_MARKIT_FILE"
#    The FILE_MESSAGE is a one line breif description about the changes.
FILE_MESSAGE=""
FILE_RELEASE=""

#    Check if no tag for file ; first time Git repository is being tagged
if ! [[ "$(git tag)" == "" ]] ; then
#    latest tagged commit across all branches
  CURRENT_RELEASE=$(git describe --tags $(git rev-list --tags --max-count=1))
else
  CURRENT_RELEASE="0.1.1"
fi

#    Check arguement 1 for --untracked-files
if [[ "$1" != "no" ]] && [[ "$1" != "normal" ]] && [[ "$1" != "all" ]] && [[ "$1" != "" ]] ; then
  new_message "${LINENO}" "${RED}ERROR${WHITE}" "  First arguement, ${1}, is NOT no, normal, all." 1>&2
  exit 1
fi

#    Change to top level git directory to include it with ${FILE_NAME} on line one item 2  #39
#    By changing ${FILE_NAME} to include the directory, all the information
#    is available to find ${FILE_NAME}'s location in GitHub or Bitbucket repository or GitLab repository
cd $(git rev-parse --show-toplevel)

#    Create FILE_LIST, remove deleted files from FILE_LIST
FILE_LIST=$(git status -s --untracked-files="${UNTRACKED_FILES}" | grep -v '^D  ' | awk '{print $2}')

#    Check if ${FILE_LIST} is zero length
if [[ -z "${FILE_LIST}" ]] ; then
  echo -e "No tracked file(s) found to mark and push." 1>&2
#    Display untracked file(s)
  if [[ $(git status --untracked-file=all -s | wc -l) ]] ; then 
    echo -e "${NORMAL}\nList of untracked file(s).${BOLD}${CYAN}\n"
    git status --untracked-file=all -s | grep '?? ' | sed 's/^??//'
    echo -e "${NORMAL}\nEnter ${BOLD}${YELLOW}git add <file-name>${NORMAL} to change <file-name> from an untracked file to a tracked file."
    echo -e "\nOr include all untracked files and directories, enter ${BOLD}${YELLOW}markit all${NORMAL}\n"
  fi
  exit 1
fi

#    Check if user has write permission
if ! $(touch "${TEMP_FILE}" > /dev/null 2>&1 ) ; then
  new_message "${LINENO}" "${RED}ERROR${WHITE}" "  ${USER} does NOT have write permission in local Git repository directory $(pwd)" 1>&2
  exit 1
fi
rm -f "${TEMP_FILE}"

#    Check if remote or local Git repository then notify user
if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  MARKITLOCAL >${BOLD}${CYAN}${MARKITLOCAL}${NORMAL}<" 1>&2 ; fi  # 1.3.614
if [[ "${MARKITLOCAL}" == "0" ]] ; then
  echo -e "${NORMAL}Files to be marked and pushed to ${BOLD}${YELLOW}remote${NORMAL} Git repository:"
elif [[ "${MARKITLOCAL}" == "1" ]] ; then
  echo -e "${NORMAL}Files to be marked for ${BOLD}${YELLOW}local${NORMAL} Git repository and NOT pushed to remote Git repository:"
else
  new_message "${LINENO}" "${RED}ERROR${WHITE}" "  Environment Variables MARKITLOCAL is not set to 0 or 1.  Current setting for MARKITLOCAL >${BOLD}${CYAN}${MARKITLOCAL}${NORMAL}<" 1>&2
  exit 1
fi

#    Prompt for release number
echo -e "\n${BOLD}${CYAN}${FILE_LIST}${NORMAL}"
echo -e "\nCurrent Git repository release number:  ${BOLD}${YELLOW}${CURRENT_RELEASE}${NORMAL}"
echo -e "Enter ${BOLD}${YELLOW}release number${NORMAL} to commit files (examples:  3.217  3.1.231  2.3.5-alpha.4  2.1.64-rc.1) or ctrl-c to stop.\n"
read -p "${BOLD}${CYAN}   "  FILE_RELEASE
echo    "${NORMAL}"
if [[ -z "${FILE_RELEASE}" ]] ; then
  FILE_RELEASE="${CURRENT_RELEASE}"
fi

#    Warn user if release number is not great than ${CURRENT_RELEASE}
#    Use case requires a WARNING not an ERROR ; see issue #14 for more information
if [[ "${CURRENT_RELEASE}" == "${FILE_RELEASE}" ]] || [[ "${CURRENT_RELEASE}" > "${FILE_RELEASE}" ]] ; then
  echo -e "${BOLD}${YELLOW}Release number may not be greater than current release number.${NORMAL}" 1>&2
fi
echo -e "${NORMAL}Using release number:  ${BOLD}${YELLOW}${FILE_RELEASE}${NORMAL}"  1>&2

#    Prompt for single line change description
echo -e "\n${NORMAL}Enter a ${BOLD}${YELLOW}one line description${NORMAL} about the changes or ctrl-c to stop."
echo -e "\t(example:  Added logic for --help; closes #12, resolves #14):\n"
read -p "${BOLD}${CYAN}   " FILE_MESSAGE
echo    "${NORMAL}"
if [[ -z "${FILE_MESSAGE}" ]] ; then
  echo -e "${NORMAL}Single-line description is ${BOLD}${YELLOW}required${NORMAL}.\nTo display your changes between commits,  ${BOLD}${YELLOW}git diff <file_name>${NORMAL}." 1>&2
  exit 1
fi

#    Current git branch
BRANCH=$(git rev-parse --abbrev-ref HEAD)

#    Mark each file
for FILE_NAME in ${FILE_LIST} ; do
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  FILE_NAME >${BOLD}${CYAN}${FILE_NAME}${NORMAL}<" 1>&2 ; fi  # 1.3.614
#
# >>> #15	In the future, Use markit solution for source code and create a wrapper during compile/build time ?
# >>>	This will change the extension case statement objective: move from comments to variables in compiled code
# >>>	move from comments in source code to variables in compiled code
# >>>	very different vision / goal
# >>>	   Use markit in the source code & insert; var BUILD_VERSION="${FILE_RELEASE}.`git rev-list HEAD | wc -l`"
# >>>	   Or use markit; to create CHAR variable found in compiled code ?
# >>>	   	opening comment x.c 'var VERSION="' and ending comment '"'
# >>>	        opening comment x.c 'char VERSION[] = "$Version: ' ${FILE_NAME}    ${FILE_RELEASE}.`git rev-list HEAD | wc -l`     ${DATE_STAMP} ${USER} ${LOCALHOST} `git describe` and ending comment '$";'
# >>>	                        x.o $Version: XXXX XXXX XXXX XXXX '$'
# >>>	        opening comment x.c 'char VERSION_MESSAGE[] = "$Version_message: ' ${FILE_MESSAGE} ` and ending comment '$";'
# >>>	                        x.o $Version_message: XXXX '$'
#
# >>> #21	Create a case statement if other non-extension files like Dockerfile or Makefile need support
  if [[ "${FILE_NAME##*/}" == "Dockerfile" ]] || [[ "${FILE_NAME##*/}" == "Makefile" ]] ; then
    BEGIN_COMMENT_CHAR="#	"
    END_COMMENT_CHAR=""
  else
# >>> #??	This does not work if the last character is '.' but it does work if more than one "."
    FILE_EXTENSION=${FILE_NAME##*\.}
    echo -e "\t${BOLD}${PURPLE}${FILE_NAME}	${FILE_EXTENSION}${NORMAL}"
    #    Single-line comment character(s) matching file extension
    #    ONLY SUPPORT single-line comments NOT multiple line block comment
    case "${FILE_EXTENSION}" in
      sh|bash|csh|tcsh|ksh|pl|PL|psh|py|rb|ps1|msh|php|php3|php4|ph3|ph4|R|yml|yaml|mk|MK|txt|tf|tfstate)
#     shell(sh|bash|csh|tcsh|ksh) perl(pl|PL|psh) Python(py) ruby(rb) PowerShell(ps1|msh) PHP(php|php3|php4|ph3|ph4) R(R) YAML(yml|yaml) Makefile(mk|MK) text(txt) Terraform(tf|tfstate)
        BEGIN_COMMENT_CHAR="# "
        END_COMMENT_CHAR=""
        ;;
      c|h|H|hpp|hxx|Hxx|HXX)
#     c(c) C header(h|H|hpp) C++ header(hxx|Hxx|HXX) 
        BEGIN_COMMENT_CHAR="/* "
        END_COMMENT_CHAR=" */"
        ;;
      cc|cpp|c++|cxx|go|java|class|jar|js|kt|kts|p|pp|pas|rs|rlib|scala|sc)
#     C++(cc|cpp|c++|cxx) Go(go) Java(java|class|jar) JavaScript(js) Kotlin(kt|kts) Pascal(p|pp|paa) Rust(rs|rlib) Scala(scala|sc)
        BEGIN_COMMENT_CHAR="// "
        END_COMMENT_CHAR=""
        ;;
      xml|html|htm)
#     XML(xml) HTML (html|htm) 
        BEGIN_COMMENT_CHAR="<!-- "
        END_COMMENT_CHAR=" -->"
        ;;
      *)
        #    Prompt for single-line beginning comment character(s)
        echo -e "\nEnter single-line  ${BOLD}${YELLOW}BEGINNING${NORMAL}${YELLOW}  comment character(s) for ${BOLD}${FILE_NAME}${NORMAL}\n\t(example: # // -- ! C !* -- // % ;;  ||  /* <!-- <!--- {- /** --[[ %{ (* <# )"
        read BEGIN_COMMENT_CHAR
        if [[ -z "${BEGIN_COMMENT_CHAR}" ]] ; then
          new_message "${LINENO}" "${RED}ERROR${WHITE}" "${BOLD}${YELLOW}  Single-line comment character(s) is required.${NORMAL}\n"  1>&2
          exit 1
        fi
        echo -e "\nEnter single-line  ${BOLD}${YELLOW}ENDING${NORMAL}${YELLOW}  comment character(s) for ${BOLD}${FILE_NAME}${NORMAL}.\nPress enter for none.\n\t(example: */ --> ---> -} */ --]] %} *) #> )"
        read END_COMMENT_CHAR
        ;;
    esac
  fi
  get_date_stamp
  head -1 "${FILE_NAME}" >> "${TEMP_FILE}"

  #    ${FILE_NAME}  ${FILE_RELEASE}.(# of commits) ${DATE_STAMP} ${REMOTE_REPOSITORY} ${BRANCH} ${USER} ${LOCALHOST} (git describe)
  if [[ "${DEBUG}" == "1" ]] ; then new_message "${LINENO}" "${YELLOW}DEBUG${WHITE}" "  FILE_NAME >${BOLD}${CYAN}${FILE_NAME}${NORMAL}< FILE_RELEASE >${BOLD}${CYAN}${FILE_RELEASE}${NORMAL}< REMOTE_REPOSITORY >${BOLD}${CYAN}${REMOTE_REPOSITORY}${NORMAL}< BRANCH >${BOLD}${CYAN}${BRANCH}${NORMAL}<" 1>&2 ; fi  # 1.3.614
  #    Check if no tag for file / first time in Git repository is being tagged
  if ! [[ "$(git tag)" == "" ]] ; then
    echo "${BEGIN_COMMENT_CHAR}	${FILE_NAME}  ${FILE_RELEASE}.$(git rev-list HEAD | wc -l)  ${DATE_STAMP}  ${REMOTE_REPOSITORY}  ${BRANCH}  ${USER}  ${LOCALHOST} $(git describe)  ${END_COMMENT_CHAR}" >> "${TEMP_FILE}"
  else
    echo "${BEGIN_COMMENT_CHAR}	${FILE_NAME}  ${FILE_RELEASE}.$(git rev-list HEAD | wc -l)  ${DATE_STAMP}  ${REMOTE_REPOSITORY}  ${BRANCH}  ${USER}  ${LOCALHOST} 'No-parent-git-tag-found-in-repository'  ${END_COMMENT_CHAR}" >> "${TEMP_FILE}"
  fi

  #    ${FILE_LIST} -->   ${FILE_MESSAGE}
  echo "${BEGIN_COMMENT_CHAR}	   ${FILE_LIST//$'\n'/ } -->   ${FILE_MESSAGE}  ${END_COMMENT_CHAR}" >> "${TEMP_FILE}"
  tail -n $(wc -l "${FILE_NAME}" | awk '{print $1  - 1}') "${FILE_NAME}" >> "${TEMP_FILE}"
  cp "${TEMP_FILE}" "${FILE_NAME}"
  rm "${TEMP_FILE}"
  #    Add file contents to the index
  git add "${FILE_NAME}"
done
echo "${NORMAL}"

#    Commit file(s)
git commit -m "${FILE_LIST} -->   ${FILE_MESSAGE}"

#    If new release number, Tag file(s)
if ! [[ "${FILE_RELEASE}" == "${CURRENT_RELEASE}" ]] ; then
  git tag -a "${FILE_RELEASE}" -m "${FILE_LIST} -->   ${FILE_MESSAGE}"
fi

#    If MARKITLOCAL not set, git push to remote Git repository
if [[ "${MARKITLOCAL}" == "0" ]] ; then
  #    Push changes to GitHub repository or Bitbucket repository or GitLab project
  git push --follow-tags  || { new_message "${LINENO}" "${RED}ERROR${WHITE}" "  If invalid username or password message then enter the following\n\tcommand to complete pushing marked files with the correcet password;\n\t\t${BOLD}git push --follow-tags${NORMAL}\n\n\tIf markit failed to push because the repository contains other work\n\tthat is not in your local Git repository.  Then enter the following\n\tcommands to pull the other changes then push your marked files;\n\t\t${BOLD}git pull\n\t\tgit push --follow-tags${NORMAL}" ; exit 1; }
  #    Notify user how to view remote Git repository
  echo -e "\n${YELLOW}Files marked and stored in ${BOLD}remote${NORMAL}${YELLOW} Git repository."
  echo    "View commits example:  ${BOLD}git log --graph --decorate --oneline --color --stat${NORMAL}"

#    If MARKITLOCAL, notify user how to view local commits
elif [[ "${MARKITLOCAL}" == "1" ]] ; then
  echo -e "\n${YELLOW}Files marked and stored in ${BOLD}local${NORMAL}${YELLOW} Git repository."
  echo    "View local commits example:  ${BOLD}git log --graph --decorate --oneline --color --stat origin..HEAD${NORMAL}"
fi

#
new_message "${LINENO}" "${YELLOW}INFO${WHITE}" "${BOLD}${CYAN}  Operation finished...${NORMAL}" 1>&2  # 1.3.614
###
